using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text.RegularExpressions;
using Kent.Boogaart.HelperTrinity;

namespace Intuipic.Data
{
	[Serializable]
	public sealed class Settings : INotifyPropertyChanged
	{
		private TimeSpan _delay;
		private bool _pinOptions;
		private DisplayOrder _displayOrder;
		private Regex _includeExpression;
		private readonly DirectoryCollection _sourceDirectories;
		private static readonly Settings _current;
		private static readonly BinaryFormatter _binaryFormatter = new BinaryFormatter();

		public static Settings Current
		{
			get
			{
				return _current;
			}
		}

		public TimeSpan Delay
		{
			get
			{
				return _delay;
			}
			set
			{
				if (value != _delay)
				{
					_delay = value;
					OnPropertyChanged("Delay");
				}
			}
		}

		public bool PinOptions
		{
			get
			{
				return _pinOptions;
			}
			set
			{
				if (value != _pinOptions)
				{
					_pinOptions = value;
					OnPropertyChanged("PinOptions");
				}
			}
		}

		public DisplayOrder DisplayOrder
		{
			get
			{
				return _displayOrder;
			}
			set
			{
				if (value != _displayOrder)
				{
					_displayOrder = value;
					OnPropertyChanged("DisplayOrder");
				}
			}
		}

		public Regex IncludeExpression
		{
			get
			{
				return _includeExpression;
			}
			set
			{
				if (value != _includeExpression)
				{
					_includeExpression = value;
					OnPropertyChanged("IncludeExpression");
				}
			}
		}

		public DirectoryCollection SourceDirectories
		{
			get
			{
				return _sourceDirectories;
			}
		}

		[field: NonSerialized]
		public event PropertyChangedEventHandler PropertyChanged;

		static Settings()
		{
			_current = Load();
		}

		public Settings()
		{
			_delay = TimeSpan.FromSeconds(5);
			_pinOptions = true;
			_displayOrder = DisplayOrder.Descending;
			_includeExpression = new Regex(@"(.*\.jpg)|(.*\.jpeg)|(.*\.bmp)|(.*\.gif)|(.*\.png)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
			_sourceDirectories = new DirectoryCollection();
		}

		private static Settings Load()
		{
			Settings settings = null;
			string path = GetPath();

			if (File.Exists(path))
			{
				try
				{
					using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None))
					{
						Version version = (Version) _binaryFormatter.Deserialize(fileStream);
						settings = _binaryFormatter.Deserialize(fileStream) as Settings;
					}
				}
				catch
				{
					//swallow - just recreate default settings
				}
			}

			if (settings == null)
			{
				settings = new Settings();
			}

			return settings;
		}

		public bool Save()
		{
			string path = GetPath();

			try
			{
				using (FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
				{
					_binaryFormatter.Serialize(fileStream, new Version(1, 0, 0, 0));
					_binaryFormatter.Serialize(fileStream, this);
				}

				return true;
			}
			catch (Exception)
			{
				//swallow
			}

			return false;
		}

		private static string GetPath()
		{
			string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Intuipic\Settings.dat");
			string directoryName = Path.GetDirectoryName(path);

			if (!Directory.Exists(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}

			return path;
		}

		private void OnPropertyChanged(string propertyName)
		{
			Debug.Assert(propertyName != null);
			EventHelper.Raise(PropertyChanged, this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
